package com.aipp.mall.h5.service;

import com.aipp.mall.common.exception.ServerException;
import com.aipp.mall.common.utils.SecurityUtil;
import com.aipp.mall.h5.domain.entity.MemberCoupon;
import com.aipp.mall.h5.domain.entity.Product;
import com.aipp.mall.h5.domain.query.MemberCouponQuery;
import com.aipp.mall.h5.mapper.MemberCouponMapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import jakarta.annotation.Resource;
import org.dromara.hutool.core.collection.CollUtil;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;

/**
 * 用户领券记录Service业务层处理
 *
 * @author zcc
 */
@Service
public class MemberCouponService {

    @Resource
    private MemberCouponMapper memberCouponMapper;

    public MemberCoupon selectValidCoupon(Long id) {
        MemberCoupon coupon = memberCouponMapper.selectById(id);
        if (coupon == null) {
            return null;
        }
        if (Objects.equals(coupon.getUseStatus(), 1)) {
            throw new ServerException("优惠券已使用");
        }
        LocalDateTime now = LocalDateTime.now();
        if (coupon.getBeginTime().isAfter(now)) {
            throw new ServerException("优惠券未到开始使用日期");
        }
        if (coupon.getEndTime().isBefore(now)) {
            throw new ServerException("优惠券已过期");
        }
        return coupon;
    }

    public IPage<MemberCoupon> selectListByH5(MemberCouponQuery query) {
        QueryWrapper<MemberCoupon> qw = new QueryWrapper<>();
        qw.eq("member_id", SecurityUtil.getLocalMember().getId());
        LocalDateTime now = LocalDateTime.now();
        if (query.getType() != null) {
            switch (query.getType()) {
                case 1:
                    //已领取
                    qw.eq("use_status", 0).ge("end_time", now).le("begin_time", now);
                    break;
                case 2:
                    //已使用
                    qw.eq("use_status", 1);
                    break;
                case 3:
                    //已过期
                    qw.eq("use_status", 0);
                    qw.and(it -> it.le("end_time", now).or().ge("begin_time", now));
                    break;
                default:
                    break;
            }
        }
        return memberCouponMapper.selectPage(Page.of(query.getPage(), query.getSize()), qw);
    }

    public List<MemberCoupon> getCanUseList(Collection<Product> products) {
        //先获取我的未过期的优惠券
        QueryWrapper<MemberCoupon> queryWrapper = new QueryWrapper<>();
        LocalDateTime now = LocalDateTime.now();
        queryWrapper.eq("member_id", SecurityUtil.getLocalMember().getId()).eq("use_status", 0).ge("end_time", now).le("begin_time", now);
        List<MemberCoupon> list = memberCouponMapper.selectList(queryWrapper);
        if (CollUtil.isEmpty(list)) {
            return list;
        }
        List<MemberCoupon> matchList = new ArrayList<>();
        list.forEach(item -> {
            if (judgeCouponCanUse(item, products)) {
                matchList.add(item);
            }
        });
        return matchList;
    }

    public Boolean judgeCouponCanUse(MemberCoupon item, Collection<Product> products) {
        //判断是否满足菜品
        if (!Objects.equals(1, item.getUseScope())) {
            List<Long> couponProducts = Arrays.stream(item.getProductIds().split(",")).map(Long::parseLong).toList();
            if (Objects.equals(2, item.getUseScope()) && products.stream().noneMatch(it -> couponProducts.contains(it.getId()))) {
                //指定商品
                return false;
            }
            if (Objects.equals(3, item.getUseScope()) && products.stream().anyMatch(it -> couponProducts.contains(it.getId()))) {
                //指定商品不包括
                return false;
            }
        }
        //计算金额是否满足
        if (item.getMinAmount() == null || item.getMinAmount().equals(BigDecimal.ZERO)) {
            //无门槛
            return true;
        }
        return item.getMinAmount().compareTo(calcMinAmount(products, item)) <= 0;
    }

    private BigDecimal calcMinAmount(Collection<Product> products, MemberCoupon coupon) {
        List<Long> ids;
        if (!Objects.equals(1, coupon.getUseScope())) {
            ids = Arrays.stream(coupon.getProductIds().split(",")).map(Long::parseLong).toList();
        } else {
            ids = new ArrayList<>();
        }
        return switch (coupon.getUseScope()) {
            case 1 -> products.stream().map(Product::getPrice).reduce(BigDecimal::add).get();
            case 2 ->
                    products.stream().filter(it -> ids.contains(it.getId())).map(Product::getPrice).reduce(BigDecimal::add).get();
            case 3 ->
                    products.stream().filter(it -> !ids.contains(it.getId())).map(Product::getPrice).reduce(BigDecimal::add).get();
            default -> BigDecimal.ZERO;
        };
    }

    public void updateCouponStatus(Long memberCouponId, Long orderId) {
        UpdateWrapper<MemberCoupon> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("id", memberCouponId).set("use_status", 1).set("use_time", LocalDateTime.now()).set("order_id", orderId);
        memberCouponMapper.update(null, updateWrapper);
    }

    public void backCoupon(List<Long> couponIdList) {
        UpdateWrapper<MemberCoupon> updateWrapper = new UpdateWrapper<>();
        updateWrapper.in("id", couponIdList).set("use_status", 0).set("use_time", null).set("order_id", null);
        memberCouponMapper.update(null, updateWrapper);
    }
}
